package me.yushuai.wukong.base.service;

import me.yushuai.wukong.base.api.dto.AllocateLocationDTO;
import me.yushuai.wukong.base.api.dto.CreateLocationDTO;
import me.yushuai.wukong.base.api.dto.LocDTO;
import me.yushuai.wukong.base.api.dto.UpdateLocationDTO;
import me.yushuai.wukong.base.entity.Location;
import me.yushuai.wukong.common.api.AbstractPageable;
import me.yushuai.wukong.common.dto.PageDTO;
import me.yushuai.wukong.common.error.WuKongException;
import me.yushuai.wukong.common.exceptin.BizIdNotExistException;
import me.yushuai.wukong.common.exceptin.BusinessException;
import me.yushuai.wukong.common.exceptin.NotExistException;
import me.yushuai.wukong.common.service.BaseService;
import org.springframework.data.jpa.domain.Specification;

import java.util.Collection;
import java.util.List;

/**
 * 库位业务接口
 *
 * @author zhoushuai@189.cn
 * @since 2022-08-31
 */
public interface LocService extends BaseService {

    /**
     * 新建一条库位信息
     *
     * @param createLocationDTO 库位信息
     * @return 返回库位信息编号
     * @throws WuKongException 当库位已存在时抛出异常
     */
    Long createLocation(CreateLocationDTO createLocationDTO) throws WuKongException;

    /**
     * 修改库位信息
     *
     * @param updateLocationDTO 库位信息
     * @return 返回修改后的库位编号
     * @throws WuKongException 当库位不存在时抛出异常
     */
    Long updateLocation(UpdateLocationDTO updateLocationDTO) throws WuKongException;

    /**
     * 删除一条库位信息
     *
     * @param locationId 库位编号
     * @throws WuKongException 当库位编码不存在时抛出异常
     */
    void deleteLocation(Long locationId) throws WuKongException;

    /**
     * 通过ID查询库位的详细信息
     *
     * @param locationId 库位编号
     * @return 返回库位的详细信息
     * @throws NotExistException 当库位不存在时抛出异常
     */
    LocDTO findById(Long locationId) throws NotExistException;

    LocDTO findByBizId(String bizId) throws BizIdNotExistException;

    /**
     * checking the locId of Location if allowed receiving.
     *
     * @param locId the locId is id of Location
     * @return when the locId of Location not allow receiving than return false otherwise return true.
     * @throws NotExistException when the locId not exists, then throw exception.
     */
    boolean allowedReceiving(Long locId) throws NotExistException;


    /**
     * 根据货物信息为自动为货物分配用于存放的库位
     *
     * @param dto 货物详细信息
     */
    LocDTO allocateLocation(AllocateLocationDTO dto);


    /**
     * 通过Id批量查询库位信息
     *
     * @param ids Id列表
     * @return 返回库位列表
     */
    List<LocDTO> findAllByIds(Collection<Long> ids) throws BusinessException;

    /**
     * 分页检查库位信息
     *
     * @param pageable 分页信息
     * @param spec     分页条件信息
     * @return 返回分页记录信息
     */
    PageDTO<LocDTO> pageSearchLoc(AbstractPageable pageable, Specification<Location> spec);

    /**
     * 断言库位编号检查存在
     *
     * @param locationId 库位编号
     * @throws WuKongException 当库位编号不存在时抛出异常
     */
    void assertLocationIdHasExist(Long locationId) throws WuKongException;

    /**
     * 断言库位编码不存在
     *
     * @param locationCode 库位编码
     * @throws WuKongException 当库位编码存在时抛出异常
     */
    void assertBizIdNotExist(String locationCode) throws WuKongException;

    /**
     * 检查库位编号是否存在，如果存在返回true否则返回false
     *
     * @param locationId 库位编号
     * @return 返回库位信息
     */
    Boolean checkHasExistLocationId(Long locationId);


    /**
     * 通过仓库Id和库位Id检查库位是否存在
     *
     * @param warehouseId 仓库Id
     * @param locId       库位Id
     * @return 返回true表示库存存在否则表示不存在
     */
    boolean existsByWarehouseIdAndLocId(Long warehouseId, Long locId);

    /**
     * 通过仓库业务Id和库位业务Id检查库位是否存在
     *
     * @param warehouseBizId 仓库的业务Id
     * @param locBizId       库位的业务Id
     * @return 返回true表示库存存在否则表示不存在
     */
    boolean existsByWarehouseBizIdAndLocBizId(String warehouseBizId, String locBizId);


}
